<script setup lang="ts">
import { RefreshLeft, Plus } from "@element-plus/icons-vue";
import { reactive, ref, nextTick, watch, computed } from "vue";
import { useUserStore } from "@/store/modules/user";
import Avatar from "@/assets/images/avatar.png";
import { isvalidPhone, validEmail } from "@/utils/index";
import { encrypt } from "@/utils/rsaEncrypt";
import {
  getUserLogs,
  editUserCenter,
  updateAvatar,
  updatePass,
  resetEmailCode,
  updateEmail
} from "@/api/userCenter";
import { cloneDeep } from "@pureadmin/utils";
import { ElNotification, genFileId, ElMessage } from "element-plus";
import cropping from "@/views/components/cropping/index.vue";
const useUserStoreInfo = useUserStore();

const baseApi = ref(import.meta.env.VITE_AVA_PATH_BASE);

const userCom = computed(() => {
  return useUserStoreInfo.user;
});
const formRules = ref(null);
const avaUpload = ref(null);
const croppingImg = ref(null);
const dialogVisible = ref(false);
const imageUrl = ref("");
const imgFile = ref(null);
const returnUp = () => {
  imageUrl.value = "";
  imgFile.value = null;
  nextTick(() => {
    avaUpload.value!.clearFiles();
  });
};
const avaCannel = () => {
  imageUrl.value = "";
  imgFile.value = null;
  dialogVisible.value = false;
  croppingImg.value && croppingImg.value.setCropperImgNull();
  nextTick(() => {
    avaUpload.value!.clearFiles();
  });
};
function base64ToBlob(base64Data) {
  const dataArr = base64Data.split(","); // 根据,来分隔
  const imageType = dataArr[0].match(/:(.*?);/)[1]; // 获取文件类型。使用正则捕获 image/jpeg
  const textData = window.atob(dataArr[1]); // 使用atob() 将base64 转为文本文件
  const arrayBuffer = new ArrayBuffer(textData.length); // 创建一个二进制数据缓冲区，可以理解为一个数组
  const uint8Array = new Uint8Array(arrayBuffer); // 创建一个类型化数组对象，可以理解为上面的数组的成员，给这个对象赋值就会放到上面的数组中。
  for (let i = 0; i < textData.length; i++) {
    uint8Array[i] = textData.charCodeAt(i); // 将文本文件转为UTF-16的ASCII, 放到类型化数组对象中
  }
  return [new Blob([arrayBuffer], { type: imageType }), imageType.slice(6)]; // 返回两个值，一个Blob对象，一个图片格式（如jpeg）
}
function toFormData(base64Data) {
  const [imageBlob, imageType] = base64ToBlob(base64Data); // 获取处理好的Blob 和文件类型
  console.log(imageType, "imageType");
  const formData = new FormData();
  formData.append("avatar", imageBlob, `${Date.now()}.${imageType}`); // 添加到表单，传入文件名
  return formData;
}
const avaSubmit = async () => {
  if (imageUrl.value) {
    let data = toFormData(croppingImg.value.cropperImg);
    await updateAvatar(data);
    ElNotification({
      title: "系统提示",
      message: "头像上传成功",
      type: "success"
    });
    avaCannel();
    useUserStoreInfo.loginGetUserInfo();
  } else {
    avaCannel();
  }
};
const fileChange = file => {
  if (file.raw.size / 1024 / 1024 > 2) {
    ElMessage.error("头像最大不能超过 2MB!");
    avaUpload.value!.clearFiles();
    return false;
  }
  imgFile.value = file;
  imageUrl.value = URL.createObjectURL(file.raw!);
};
const handleExceed = files => {
  avaUpload.value!.clearFiles();
  const file = files[0];
  file.uid = genFileId();
  avaUpload.value!.handleStart(file);
};
const toggleShow = () => {
  // 显示上传头像 dialog
  dialogVisible.value = true;
};
const handleClose = d => {
  avaCannel();
  d();
};
const activeName = ref("first");
const validPhone = (rule, value, callback) => {
  if (!value) {
    callback(new Error("请输入电话号码"));
  } else if (!isvalidPhone(value)) {
    callback(new Error("请输入正确的11位手机号码"));
  } else {
    callback();
  }
};
const form = reactive({
  data: {
    id: userCom.value?.id,
    nickName: userCom.value?.nickName,
    phone: userCom.value?.phone,
    gender: userCom.value?.gender
  },
  rules: {
    nickName: [
      { required: true, message: "请输入用户昵称", trigger: "blur" },
      { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" }
    ],
    phone: [{ required: true, trigger: "blur", validator: validPhone }]
  }
});
const saveLoading = ref(false);
const loading = ref(false);
const doSubmit = () => {
  formRules.value.validate(async valid => {
    if (valid) {
      saveLoading.value = true;
      let data = cloneDeep(form.data);
      await editUserCenter(data);
      saveLoading.value = false;
      ElNotification({
        title: "系统提示",
        message: "编辑成功",
        type: "success"
      });
      useUserStoreInfo.loginGetUserInfo();
    }
  });
};
const tableData = reactive({
  data: []
});
const pageObj = reactive({
  data: {
    currentPage: 1,
    pageSize: 10,
    total: 0
  }
});
const handleSizeChange = size => {
  search();
};
const handleCurrentChange = () => {
  getList();
};
const getData = () => {
  loading.value = true;
  return new Promise<any>(async (resolve, reject) => {
    let data = await getUserLogs({
      current: pageObj.data.currentPage,
      size: pageObj.data.pageSize,
      sort: "id,desc"
    });
    loading.value = false;
    resolve(data);
  });
};
const getList = async () => {
  let data = await getData();
  tableData.data = data.content;
  pageObj.data.total = data.totalElements;
};
const search = async () => {
  pageObj.data.currentPage = 1;
  let data = await getData();
  tableData.data = data.content;
  pageObj.data.total = data.totalElements;
};
const init = () => {
  search();
};
const handleClick = tab => {
  if (tab.paneName === "second") {
    init();
  }
};
const editPwd = ref(false);
const editEmail = ref(false);
const confirmPass = (rule, value, callback) => {
  if (value) {
    if (pwdForm.data.newPass !== value) {
      callback(new Error("两次输入的密码不一致"));
    } else {
      callback();
    }
  } else {
    callback(new Error("请再次输入密码"));
  }
};
const pwdRef = ref(null);
const emailRef = ref(null);
const pwdForm = reactive({
  data: {
    oldPass: undefined,
    newPass: undefined,
    confirmPass: undefined
  },
  rules: {
    oldPass: [{ required: true, message: "请输入旧密码", trigger: "blur" }],
    newPass: [
      { required: true, message: "请输入新密码", trigger: "blur" },
      { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
    ],
    confirmPass: [{ required: true, validator: confirmPass, trigger: "blur" }]
  }
});
const validMail = (rule, value, callback) => {
  if (value === "" || value === null) {
    callback(new Error("新邮箱不能为空"));
  } else if (value === userCom.value.email) {
    callback(new Error("新邮箱不能与旧邮箱相同"));
  } else if (validEmail(value)) {
    callback();
  } else {
    callback(new Error("邮箱格式错误"));
  }
};
const emailForm = reactive({
  data: {
    email: undefined,
    code: undefined,
    pass: undefined
  },
  rules: {
    pass: [{ required: true, message: "当前密码不能为空", trigger: "blur" }],
    email: [{ required: true, validator: validMail, trigger: "blur" }],
    code: [{ required: true, message: "验证码不能为空", trigger: "blur" }]
  }
});
const resetPwd = () => {
  pwdForm.data = {
    oldPass: undefined,
    newPass: undefined,
    confirmPass: undefined
  };
  nextTick(() => {
    pwdRef.value && pwdRef.value.clearValidate();
  });
};
const resetEmail = () => {
  emailForm.data = {
    email: undefined,
    code: undefined,
    pass: undefined
  };
  nextTick(() => {
    emailRef.value && emailRef.value.clearValidate();
  });
};
const editPwdhandleClose = d => {
  resetPwd();
  d();
};
const editEmailhandleClose = d => {
  resetEmail();
  d();
};
const pwdCannel = () => {
  resetPwd();
  editPwd.value = false;
};
const emailCannel = () => {
  resetEmail();
  editEmail.value = false;
};
const editPwdHanle = () => {
  editPwd.value = true;
};
const editEmailHanle = () => {
  editEmail.value = true;
};
const pwdSubmit = () => {
  pwdRef.value &&
    pwdRef.value.validate(async valid => {
      if (valid) {
        let data = cloneDeep(pwdForm.data);
        let newData = {
          newPass: encrypt(data.newPass),
          oldPass: encrypt(data.oldPass)
        };
        await updatePass(newData);
        ElNotification({
          title: "系统提示",
          message: "密码修改成功，请重新登录",
          type: "success"
        });
        useUserStoreInfo.logOut();
      }
    });
};
const emailSubmit = () => {
  emailRef.value &&
    emailRef.value.validate(async valid => {
      if (valid) {
        let data = cloneDeep(emailForm.data);
        let newData = {
          password: encrypt(data.pass),
          email: data.email
        };
        await updateEmail(newData, data.code);
        ElNotification({
          title: "系统提示",
          message: "邮箱修改成功",
          type: "success"
        });
        useUserStoreInfo.loginGetUserInfo();
        emailCannel();
      }
    });
};
const codeLoading = ref(false);
const isDisabled = ref(false);
const buttonName = ref("获取验证码");
const time = ref(60);
const timer = ref(null);
const sendCode = () => {
  if (emailForm.data.email && emailForm.data.email !== userCom.value.email) {
    codeLoading.value = true;
    buttonName.value = "验证码发送中";
    resetEmailCode({ email: emailForm.data.email })
      .then(res => {
        ElMessage({
          message: "发送成功，验证码有效期5分钟",
          type: "success"
        });
        codeLoading.value = false;
        isDisabled.value = true;
        buttonName.value = time.value-- + "秒后重新发送";
        timer.value = window.setInterval(function () {
          buttonName.value = time.value + "秒后重新发送";
          --time.value;
          if (time.value < 0) {
            buttonName.value = "重新发送";
            time.value = 60;
            isDisabled.value = false;
            window.clearInterval(timer.value);
          }
        }, 1000);
      })
      .catch(err => {
        resetEmail();
        codeLoading.value = false;
        console.log(err.response.data.message);
      });
  }
};
</script>

<template>
  <div class="w-full main h-[calc(100%-29px)]">
    <el-dialog
      v-model="editEmail"
      title="修改邮箱"
      width="30%"
      :before-close="editEmailhandleClose"
    >
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="emailCannel">取消</el-button>
          <el-button type="primary" @click="emailSubmit"> 确定 </el-button>
        </span>
      </template>
      <el-form
        ref="emailRef"
        :model="emailForm.data"
        :rules="emailForm.rules"
        label-width="80px"
      >
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="新邮箱" prop="email">
              <div class="flex items-center w-full">
                <div class="flex-1">
                  <el-input v-model="emailForm.data.email" auto-complete="on" />
                </div>
                <div>
                  <el-button
                    :loading="codeLoading"
                    :disabled="isDisabled"
                    size="small"
                    @click="sendCode"
                    >{{ buttonName }}</el-button
                  >
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="验证码" prop="code">
              <el-input v-model="emailForm.data.code" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="当前密码" prop="pass">
              <el-input v-model="emailForm.data.pass" type="password" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-dialog>
    <el-dialog
      v-model="editPwd"
      title="修改密码"
      width="30%"
      :before-close="editPwdhandleClose"
    >
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="pwdCannel">取消</el-button>
          <el-button type="primary" @click="pwdSubmit"> 确定 </el-button>
        </span>
      </template>
      <el-form ref="pwdRef" :model="pwdForm.data" :rules="pwdForm.rules">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="旧密码" prop="oldPass">
              <el-input v-model="pwdForm.data.oldPass" type="password" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="新密码" prop="newPass">
              <el-input v-model="pwdForm.data.newPass" type="password" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="确认密码" prop="confirmPass">
              <el-input v-model="pwdForm.data.confirmPass" type="password" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-dialog>
    <el-dialog
      v-model="dialogVisible"
      title="头像上传"
      width="30%"
      :before-close="handleClose"
    >
      <el-upload
        v-show="!imageUrl"
        ref="avaUpload"
        accept=".png,.PNG,.jpg,.JPG,.jpeg,.JPEG"
        class="upload-demo"
        drag
        :limit="1"
        action="/"
        :auto-upload="false"
        :on-change="fileChange"
        :on-exceed="handleExceed"
      >
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
      </el-upload>
      <cropping
        v-if="imageUrl"
        ref="croppingImg"
        :imgPath="imageUrl"
        @prev="returnUp"
      />
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="avaCannel">取消</el-button>
          <el-button type="primary" @click="avaSubmit"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
    <el-row class="w-full" :gutter="20">
      <el-col
        :xs="24"
        :sm="24"
        :md="8"
        :lg="6"
        :xl="5"
        style="margin-bottom: 10px"
      >
        <el-card class="box-card">
          <template v-slot:header>
            <div class="clearfix">
              <span>个人信息</span>
            </div>
          </template>
          <div>
            <div style="text-align: center">
              <div class="el-upload">
                <img
                  :src="
                    userCom?.avatarName
                      ? baseApi + '/' + userCom.avatarName
                      : Avatar
                  "
                  title="点击上传头像"
                  class="avatar"
                  @click="toggleShow"
                />
              </div>
            </div>
            <ul class="user-info">
              <li>
                <div style="height: 100%">
                  <svg-icon icon-class="login" /> 登录账号
                  <div class="user-right">{{ userCom.username }}</div>
                </div>
              </li>
              <li>
                <svg-icon icon-class="user1" /> 用户昵称
                <div class="user-right">{{ userCom.nickName }}</div>
              </li>
              <li>
                <svg-icon icon-class="dept" /> 所属部门
                <div class="user-right">{{ userCom.dept.name }}</div>
              </li>
              <li>
                <svg-icon icon-class="phone" /> 手机号码
                <div class="user-right">{{ userCom.phone }}</div>
              </li>
              <li>
                <svg-icon icon-class="email" /> 用户邮箱
                <div class="user-right">{{ userCom.email }}</div>
              </li>
              <li>
                <svg-icon icon-class="anq" /> 安全设置
                <div class="user-right">
                  <el-button type="primary" text link @click="editPwdHanle"
                    >修改密码</el-button
                  >
                  <el-button type="primary" text link @click="editEmailHanle"
                    >修改邮箱</el-button
                  >
                </div>
              </li>
            </ul>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="24" :md="16" :lg="18" :xl="19">
        <!--    用户资料    -->
        <el-card class="box-card">
          <el-tabs v-model="activeName" @tab-click="handleClick">
            <el-tab-pane label="用户资料" name="first">
              <el-form
                ref="formRules"
                :model="form.data"
                :rules="form.rules"
                style="margin-top: 10px"
                size="small"
                label-width="65px"
              >
                <el-form-item label="昵称" prop="nickName">
                  <el-input v-model="form.data.nickName" style="width: 35%" />
                  <span style="margin-left: 10px; color: #c0c0c0"
                    >用户昵称不作为登录使用</span
                  >
                </el-form-item>
                <el-form-item label="手机号" prop="phone">
                  <el-input v-model="form.data.phone" style="width: 35%" />
                  <span style="margin-left: 10px; color: #c0c0c0"
                    >手机号码不能重复</span
                  >
                </el-form-item>
                <el-form-item label="性别">
                  <el-radio-group
                    v-model="form.data.gender"
                    style="width: 178px"
                  >
                    <el-radio label="男">男</el-radio>
                    <el-radio label="女">女</el-radio>
                  </el-radio-group>
                </el-form-item>
                <el-form-item label="">
                  <el-button
                    :loading="saveLoading"
                    size="mini"
                    type="primary"
                    @click="doSubmit"
                    >保存配置</el-button
                  >
                </el-form-item>
              </el-form>
            </el-tab-pane>
            <!--    操作日志    -->
            <el-tab-pane label="操作日志" name="second">
              <el-table
                v-loading="loading"
                :data="tableData.data"
                style="width: 100%"
              >
                <el-table-column prop="description" label="行为" />
                <el-table-column prop="requestIp" label="IP" />
                <el-table-column
                  :show-overflow-tooltip="true"
                  prop="address"
                  label="IP来源"
                />
                <el-table-column prop="browser" label="浏览器" />
                <el-table-column prop="time" label="请求耗时" align="center">
                  <template #default="scope">
                    <el-tag v-if="scope.row.time <= 300"
                      >{{ scope.row.time }}ms</el-tag
                    >
                    <el-tag v-else-if="scope.row.time <= 1000" type="warning"
                      >{{ scope.row.time }}ms</el-tag
                    >
                    <el-tag v-else type="danger">{{ scope.row.time }}ms</el-tag>
                  </template>
                </el-table-column>
                <el-table-column align="right">
                  <template #header>
                    <div
                      style="
                        display: inline-block;
                        float: right;
                        cursor: pointer;
                      "
                      @click="init"
                    >
                      创建日期
                      <el-icon style="margin-left: 40px"
                        ><RefreshLeft
                      /></el-icon>
                    </div>
                  </template>
                  <template #default="scope">
                    <span>{{ scope.row.createTime }}</span>
                  </template>
                </el-table-column>
              </el-table>
              <!--分页组件-->
              <el-pagination
                v-model:current-page="pageObj.data.currentPage"
                v-model:page-size="pageObj.data.pageSize"
                :page-sizes="[10, 20, 30, 40, 50, 100]"
                layout="total, sizes, prev, pager, next, jumper"
                :total="pageObj.data.total"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </el-tab-pane>
          </el-tabs>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>
<style scoped lang="scss">
.avatar {
  width: 120px;
  height: 120px;
  border-radius: 50%;
}

.user-info {
  padding-left: 0;
  list-style: none;

  li {
    padding: 11px 0;
    font-size: 13px;
    border-bottom: 1px solid #f0f3f4;
  }

  .user-right {
    float: right;

    a {
      color: #317ef3;
    }
  }
}
</style>
